/*
	Copyright (c) 2007, ANYwebcam.com Pty Ltd. All rights reserved.

	The software in this package is published under the terms of the BSD style 
	license, a copy of which has been included with this distribution in the 
	license.txt file.
*/
package com.anywebcam.di.component
{
	import com.anywebcam.di.*;
	import com.anywebcam.di.error.UnsettableSetterError;	
	import com.anywebcam.reflection.MethodInfo;

	/**
	 * Wraps an existing object instance in a DIComponent to allow the DIContainer to manage it
	 */
	public class InstanceComponent extends InstantiatingComponent
	{
		private var _instance:Object;
		private var _options:Object;
		private var _setParametersCount:int = 0;

		public function InstanceComponent( key:Object, instance:Object, parameters:Array = null, options:Object = null )
		{
			var type:Class = instance.constructor as Class;
			
			super( key, type, parameters );
			
			_instance 	= instance;
			_options 	= options || { setParameters: 'once' };
		}
		
		/**
		 * @inheritDoc
		 */
		override public function getInstance( container:DIContainer ):Object
		{
			if( (_options.setParameters == 'once' && _setParametersCount == 0) || _options.setParameters == 'every' )
			{
				_setParametersCount++;
				
				// ripped straight from the SetterInjectionComponent
				// todo: make there only one instance of this code between the two components, create another subclass or helper function
				// loop over each parameter
				if( parameters ) parameters.forEach( function( param:Object, index:int, array:Array ):void
				{
					var key:String;
					var value:Object;
					var setter:MethodInfo;

					if( param is String )
					{
						key = param as String;

						setter = classInfo.setter( param as String );
						if( !setter ) throw new UnsettableSetterError( this, key );

						value = getParameterValue( container, setter.parameters[0] );
					}
					else
					{
						for( var property:String in param )
						{
							key = property;
							
							setter = classInfo.setter( property );
							if( !setter ) throw new UnsettableSetterError( this, key );

							value = getParameterValue( container, param[ key ] );
							break;
						}
					}

					setter.invoke( _instance, value );
				});
			}
			
			return _instance;
		}
	}
}